home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 10 / The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso / PC_SIGCD / 02 / 0 / DISK0202.ZIP / INT_PKG.ASM < prev    next >
Assembly Source File  |  1984-01-01  |  13KB  |  403 lines

  1.     INCLUDE    TITLE.MAC
  2.     .TITLE    <INT_PKG -- Interrupt Vector Interface Routines>
  3.     .SBTTL    History
  4.  
  5. ; int_pkg.asm  17 Nov 83  Craig Milo Rogers at USC/ISI
  6. ;    Debugged in non-DOS, DOS 1, and DOS 2 configurations.
  7. ;    Set to non-DOS for actual use.
  8. ;    Added int_prev().
  9. ; int_pkg.asm  15 Nov 83  Craig Milo Rogers at USC/ISI
  10. ;    Created this package to change and restore interrupt vectors
  11. ; on the IBM PC.
  12.  
  13.     .SBHED    Overview
  14.  
  15. ;    This package manages interrupt vectors on the IBM PC.
  16. ;
  17. ; 1)    The package may be compiled to use the DOS calls to get and
  18. ;    set interrupt vectors, or it may be compiled to do these
  19. ;    tasks directly.
  20. ;
  21. ; 2)    The basic services that this module provides to clients are
  22. ;    to set and restore interrupt vectors.  When an interrupt vector
  23. ;    is set, its old contents are saved.  The old contents may be
  24. ;    restored upon demand by a client, or when a package termination
  25. ;    (clean-up) call is issued.
  26. ;
  27. ; 3)    Nested calls to set and restore the same interrupt vector are
  28. ;    not supported.
  29. ;
  30. ; 4)    The old interrupt vectors are saved in a local storage area.
  31. ;    The length of the storage area is an assembly parameter.  A
  32. ;    fixed area was selected over a linked list because a linked
  33. ;    list is more likely to be damaged by a runaway program.
  34.  
  35. ;    Entry points (Lattice C 1.05 calling conventions):
  36.  
  37. ; void
  38. ; int_ini()            /* Initializes the saved interrupt database.*/
  39.  
  40. ; bool                /* FALSE ==> vector in use or out of mem. */
  41. ; int_setup(vec, newip, newcs)    /* Setup an interrupt vector. */
  42. ; int vec;            /* Interrupt vector number. */
  43. ; int newip;            /* Instruction pointer for interrupt code. */
  44. ; int newcs;            /* Code segment for interrupt code. */
  45. ;                /* Together, newip and newcs are the same
  46. ;                 * as a Large model pointer-to-function.
  47. ;                 * However, C routines may not be directly
  48. ;                 * called this way, since lots of registers
  49. ;                 * must be saved and setup first before C
  50. ;                 * code can be used. */
  51.  
  52. ; long                /* Actually, a pointer to a "function". */
  53. ;                /* 0L ==> vector not saved, or was empty. */
  54. ; int_prev(vec)            /* Returns prev. contents of the vector. */
  55. ; int vec;            /* Interrupt vector number. */
  56.  
  57. ; bool                /* FALSE ==> vector not in use. */
  58. ; int_restore(vec)        /* Restore an interrupt vector. */
  59. ; int vec;            /* Interrupt vector number. */
  60.  
  61. ; void
  62. ; int_trm()            /* Terminate, ie restore all vectors. */
  63.  
  64.     .SBHED    Declarations
  65.  
  66. IF1
  67.     INCLUDE    DOS.MAC    ; C segments.
  68.     INCLUDE    BMAC.MAC    ; C calling conventions.
  69. ENDIF
  70.  
  71.  
  72. ;    Here are the two configuration parameters.  Ideally these
  73. ; should come from an include file, not the source file.
  74.  
  75. NODOS    EQU    0        ; 0 ==> Use DOS calls, 1 ==> Avoid DOS.
  76. NSAVVEC    EQU    10        ; Nomber of vectors to handle.
  77.  
  78.  
  79. ;    The following structure saves old interrupt vector contents:
  80.  
  81. SVEC    STRUC            ; Saves old vectors.
  82. SAVVEC    DW    ?        ; Saved vector number.
  83. SAVIP    DW    ?        ; Saved Instruction Pointer.
  84. SAVCS    DW    ?        ; Saved Code Segment.
  85. SVEC    ENDS
  86.  
  87. NOVEC    EQU    0FFFFH        ; Indicates an unused entry.
  88.  
  89.  
  90. ;    Return Codes:
  91.  
  92. TRUE    EQU    1        ; Truth.
  93. FALSE    EQU    0        ; Falsehood.
  94.  
  95.     .SBHED    <Data Storage>
  96.  
  97. ABS0    SEGMENT    AT 0H        ; Segment with interrupt vectors.
  98. ABS0    ENDS
  99.  
  100.     DSEG
  101.  
  102. SAVAREA    SVEC    NSAVVEC DUP(<>)    ; Saved interrupt vector blocks.
  103.  
  104. IFE NODOS            ; Are we using DOS?
  105. DOSTYPE    DW    ?        ; Gets the DOS level.
  106. ENDIF
  107.  
  108.     ENDDS
  109.  
  110.     PSEG
  111.     DB    '(C) Copyright Inner Loop Software, 1983'
  112.  
  113.     .SBHED    <FINDVEC -- Internal Routine to Find a Vector>
  114.  
  115. ;    Called with the vector in AX.
  116. ;    Returns with a pointer to the vector save block in SI.
  117. ;        Carry clear -- found the vector save entry.
  118. ;        Carry set -- didn't find the vector save entry.
  119. ;    Modifies:  CX, SI, CF
  120.  
  121. FINDVEC    PROC    NEAR            ; Internal routine.
  122.  
  123.     MOV    SI,OFFSET SAVAREA    ; Address of save area.
  124.     MOV    CX,NSAVVEC        ; Number of vector save entries.
  125.  
  126. FINDLOOP:
  127.     CMP    [SI].SAVVEC,AX        ; Is this the vector?
  128.      JE    FOUNDIT            ;   (yup, too bad)
  129.     ADD    SI,TYPE SVEC        ; Advance SI to next save entry.
  130.     LOOP    FINDLOOP        ; Loop for number of save entries.
  131.  
  132.     STC                ; Set the carry flag -- not found.
  133.     RET                ; Return with error set.
  134.  
  135. FOUNDIT:
  136.     CLC                ; Clear carry - found entry.
  137.     RET                ; Return, no error.
  138.  
  139. FINDVEC    ENDP
  140.  
  141.     .SBHED    <INT_INI -- Initialize Saved Interrupt Database>
  142.  
  143. ; void
  144. ; int_ini()            /* Initializes the saved interrupt database.*/
  145.  
  146.     BENTRY    INT_INI
  147.  
  148.     MOV    SI,OFFSET SAVAREA    ; Address of save area.
  149.     MOV    CX,NSAVVEC        ; Number of vector save entries.
  150.     XOR    AX,AX            ; Clear AX for a handy source of 0.
  151.  
  152. INILOOP:
  153.     MOV    [SI].SAVVEC,NOVEC    ; Indicate no vector present.
  154.     MOV    [SI].SAVIP,AX        ; Clear saved Instruction Pointer.
  155.     MOV    [SI].SAVCS,AX        ; Clear saved Code Segment.
  156.     ADD    SI,TYPE SVEC        ; Advance SI to next save entry.
  157.     LOOP    INILOOP            ; Loop for number of save entries.
  158.  
  159. IFE NODOS                ; Are we using DOS?
  160.     MOV    AH,30H            ; Get DOS Version function number.
  161.     INT    21H            ; DOS Function Call.
  162.     MOV    DOSTYPE,AX        ; Save the returned value.
  163. ENDIF
  164.  
  165.     BEND    INT_INI            ; That's all for initialization.
  166.  
  167.     .SBHED    <INT_SETUP -- Setup an Interrupt Vector>
  168.  
  169. ; bool                /* FALSE ==> vector in use or out of mem. */
  170. ; int_setup(vec, newip, newcs)    /* Setup an interrupt vector. */
  171. ; int vec;            /* Interrupt vector number. */
  172. ; int newip;            /* Instruction pointer for interrupt code. */
  173. ; int newcs;            /* Code segment for interrupt code. */
  174. ;                /* Together, newip and newcs are the same
  175. ;                 * as a Large model pointer-to-function.
  176. ;                 * However, C routines may not be directly
  177. ;                 * called this way, since lots of registers
  178. ;                 * must be saved and setup first before C
  179. ;                 * code can be used. */
  180.  
  181.     BENTRY    INT_SETU <VEC,NEWIP,NEWCS>
  182.  
  183.     MOV    AX,VEC            ; Vector for which we're looking.
  184.     CALL    FINDVEC            ; See if already allocated
  185.      JNC    SETBAD            ;   (yup, too bad)
  186.  
  187.     MOV    SI,OFFSET SAVAREA    ; Address of save area.
  188.     MOV    CX,NSAVVEC        ; Number of vector save entries.
  189.  
  190. SETFREE:
  191.     CMP    [SI].SAVVEC,NOVEC    ; Is this a free entry?
  192.      JE    SETVEC            ;   (yup)
  193.     ADD    SI,TYPE SVEC        ; Advance SI to next save entry.
  194.     LOOP    SETFREE            ; Loop for number of save entries.
  195.  
  196. SETBAD:
  197.     MOV    AX,FALSE        ; Vector in use, or no free space.
  198.     JMP SHORT SETDONE        ; Go return to the user.
  199.  
  200. SETVEC:                    ; Let's set the interrupt vector.
  201. IF NODOS
  202.  
  203. ;    This code copies the old vector contents into the vector save
  204. ; block and sets the new vector contents, as an atomic operation.  This
  205. ; eliminates the possibility of an interrupt changing the vector's
  206. ; contents while the vector is being saved.
  207.  
  208.     MOV    BX,ABS0            ; Get start of interrupt vectors.
  209.     MOV    ES,BX            ; ES is vector segment.
  210.     ASSUME    ES:ABS0
  211.  
  212.                     ; AX still has target vector.
  213.     MOV    BX,AX            ; Transfer vector number.
  214.     ADD    BX,BX            ; Convert to vector address.
  215.     ADD    BX,BX
  216.     MOV    CX,NEWIP        ; Get the new vector offset.
  217.     MOV    DX,NEWCS        ; Get the new vector section.
  218.  
  219.     PUSHF                ; Save current interrupt setting.
  220.     CLI                ; ******* Disable Interrupts *******
  221.     XCHG    CX,ES:[BX]        ;;; Set vector's Instruction Ptr.
  222.     XCHG    DX,ES:[BX+2]        ;;; Set vector's Segment Number.
  223.     MOV    [SI].SAVVEC,AX        ;;; Mark this save block used.
  224.     MOV    [SI].SAVIP,CX        ;;; Store the old vector offset.
  225.     MOV    [SI].SAVCS,DX        ;;; Store the old vector segment.
  226.     POPF                ;;; ******* Restore Interrupts *******
  227.                     ;;; (Next instruction still disabled)
  228.     ASSUME    ES:NOTHING
  229. ELSE
  230.  
  231. ;    This code saves the old contents of the vector, then sets the new
  232. ; contents.  The operations are not atomic, so there is an implicit
  233. ; assumption that the interrupt vector will not be changed (by an
  234. ; interrupt routine) which this routine is running.
  235.  
  236.     CMP    BYTE PTR DOSTYPE,2    ; Is this DOS 2 or greater?
  237.      JGE    SETDOS2            ;   (yup)
  238.  
  239. ;    This system is pre-DOS 2.  Save the old vector without DOS.
  240.  
  241.     MOV    BX,ABS0            ; Get start of interrupt vectors.
  242.     MOV    ES,BX            ; ES is vector segment.
  243.     ASSUME    ES:ABS0
  244.                     ; AX still has target vector.
  245.     MOV    BX,AX            ; Transfer vector number.
  246.     ADD    BX,BX            ; Convert to vector address.
  247.     ADD    BX,BX
  248.  
  249.     MOV    CX,ES:[BX]        ; Get vector's Instruction Ptr.
  250.     MOV    DX,ES:[BX+2]        ; Get vector's Segment Number.
  251.     MOV    [SI].SAVIP,CX        ; Store the old vector offset.
  252.     MOV    [SI].SAVCS,DX        ; Store the old vector segment.
  253.     MOV    [SI].SAVVEC,AX        ; Mark this save block used.
  254.     ASSUME    ES:NOTHING
  255.  
  256.     JMP SHORT SETDOSVEC        ; Go set the vector.
  257.  
  258. SETDOS2:
  259.  
  260. ;    Use the DOS 2 call to get old vec.  Store the vector number
  261. ; into the save block last.  This interlocks the save block contents
  262. ; so it can be referenced at interrupt level.
  263.  
  264.                     ; AX still has target vector.
  265.     MOV    AH,35H            ; DOS Get Vector function.
  266.     INT    21H            ; DOS Function Call.
  267.     MOV    [SI].SAVIP,BX        ; Store the old vector offset.
  268.     PUSH    ES            ; Store the old vector segment
  269.     POP    [SI].SAVCS        ;   via the stack.
  270.     MOV    AX,VEC            ; Get the vector number again.
  271.     MOV    [SI].SAVVEC,AX        ; Mark this save block used.
  272.                     ; Fall into SETDOSVEC...
  273.  
  274. SETDOSVEC:
  275.  
  276. ;     Call DOS to set the interrupt vector.
  277.  
  278.                     ; Vector number already in AL.
  279.     MOV    DX,NEWIP        ; Fetch the new vector offset.
  280.     PUSH    DS            ; Save our data segment.
  281.     PUSH    NEWCS            ; Fetch the new vector segment.
  282.     POP    DS            ; Transfer new segment to DS.
  283.     MOV    AH,25H            ; DOS Set Interrupt Vector function.
  284.     INT    21H            ; DOS Function Call.
  285.     POP    DS            ; Restore our data segment.
  286. ENDIF
  287.  
  288.     MOV    AX,TRUE            ; Return TRUE to caller.
  289.                     ; Fall into SETDONE...
  290. SETDONE:
  291.     BEND    INT_SETU
  292.  
  293.     .SBHED    <INT_PREV -- Return Previous Vector Contents>
  294.  
  295. ; long                /* Actually, a pointer to a "function". */
  296. ;                /* 0L ==> vector not saved, or was empty. */
  297. ; int_prev(vec)            /* Returns prev. contents of the vector. */
  298. ; int vec;            /* Interrupt vector number. */
  299.  
  300. ;    A 0L return can meas two things:  either the wrong vector was
  301. ; supplied to int_prev(), or the vector's previous contents were in fact
  302. ; zero.  0L is not a significant value for any of the vectors at the
  303. ; present time, and isn't a reasonable address for a procedure.
  304. ; However, it is quite possible for a vector to contain 0L if it has
  305. ; never been used before.  So, don't treat 0L as a fatal error, but
  306. ; don't treat it as a valid procedure, either.
  307.  
  308.     BENTRY    INT_PREV <VEC>
  309.  
  310.     MOV    AX,VEC            ; Vector for which we're looking.
  311.     CALL    FINDVEC            ; Try to find save block.
  312.      JC    PREVERR            ;   (not found)
  313.     MOV    AX,[SI].SAVCS        ; AX gets segment.
  314.     MOV    BX,[SI].SAVIP        ; BX gets offset.
  315.     JMP SHORT PREVDONE        ; Go return to the user.
  316.  
  317. PREVERR:
  318.     XOR    AX,AX            ; Failed to find target vector.
  319.     XOR    BX,BX
  320.  
  321. PREVDONE:
  322.     BEND    INT_PREV        ; That's all, return code in AX, BX.
  323.  
  324.     .SBHED    <INT_RESTORE -- Restore a Saved Vector>
  325.  
  326. ; bool                /* FALSE ==> vector not in use. */
  327. ; int_restore(vec)        /* Restore an interrupt vector. */
  328. ; int vec;            /* Interrupt vector number. */
  329.  
  330.     BENTRY    INT_REST <VEC>
  331.  
  332.     MOV    AX,VEC            ; Vector for which we're looking.
  333.     CALL    FINDVEC            ; Look for the saved vector.
  334.      JNC    RESTVEC            ;   (found it)
  335.     MOV    AX,FALSE        ; Failed to find target vector.
  336.     JMP SHORT RESTDONE        ; Go return to the user.
  337.  
  338. RESTVEC:                ; SI points to the save block.
  339.  
  340. IF NODOS
  341.     MOV    BX,AX            ; Transfer vector number.
  342.     ADD    BX,BX            ; Convert to vector address.
  343.     ADD    BX,BX
  344.     MOV    CX,[SI].SAVIP        ; Fetch the saved vector offset.
  345.     MOV    DX,[SI].SAVCS        ; Fetch the saved vector segment.
  346.     PUSH    DS            ; Save our data segment.
  347.     MOV    AX,ABS0            ; Get start of interrupt vectors.
  348.     MOV    DS,AX            ; Now work in vector segment.
  349.  
  350.     PUSHF                ; Save current interrupt setting.
  351.     CLI                ; ******* Disable Interrupts *******
  352.     MOV    [BX],CX            ;;; Restore vector's Instruction Ptr.
  353.     MOV    [BX+2],DX        ;;; Restore vector's Segment Number.
  354.     POPF                ;;; ******* Restore Interrupts *******
  355.     POP    DS            ;;; Restore our data segment.
  356. ELSE
  357.                     ; Use DOS call to restore the vector.
  358.                     ; Vector number already in AL.
  359.     MOV    DX,[SI].SAVIP        ; Fetch the saved vector offset.
  360.     PUSH    DS            ; Save our data segment.
  361.     PUSH    [SI].SAVCS        ; Fetch the saved vector segment.
  362.     POP    DS            ; Transfer saved segment to DS.
  363.     MOV    AH,25H            ; DOS Set Interrupt Vector function.
  364.     INT    21H            ; DOS Function Call.
  365.     POP    DS            ; Restore our data segment.
  366. ENDIF
  367.  
  368.     MOV    [SI].SAVVEC,NOVEC    ; Free this saved vector block.
  369.     MOV    AX,TRUE            ; Return TRUE to caller.
  370.                     ; Fall into RESTDONE...
  371.  
  372. RESTDONE:
  373.     BEND    INT_REST        ; That's all, return code in AX.
  374.  
  375.     .SBHED    <INT_TRM -- Terminate and Restore All Vectors>
  376.  
  377. ; void
  378. ; int_trm()            /* Terminate, ie restore all vectors. */
  379.  
  380.     BENTRY    INT_TRM
  381.  
  382.     MOV    SI,OFFSET SAVAREA    ; Address of save area.
  383.     MOV    CX,NSAVVEC        ; Number of vector save entries.
  384.  
  385. TRMLOOP:
  386.     CMP    [SI].SAVVEC,NOVEC    ; Is there a vector present?
  387.      JE    TRMNEXT            ;   (nope)
  388.  
  389.     PUSH    SI            ; Save SI
  390.     PUSH    CX            ;   and CX accross subroutine call.
  391.     BCALL    INT_REST <[SI].SAVVEC>    ; Call the code to restore the vector.
  392.     POP    CX            ; Restore saved registers.
  393.     POP    SI
  394.  
  395. TRMNEXT:
  396.     ADD    SI,TYPE SVEC        ; Advance SI to next save entry.
  397.     LOOP    TRMLOOP            ; Loop for number of save entries.
  398.  
  399.     BEND    INT_TRM            ; That's all.
  400.  
  401.     ENDPS
  402.     END
  403.